#ifndef __EPOLLSERVER_HPP_
#define __EPOLLSERVER_HPP_

#include<iostream>
#include<sys/epoll.h>
#include"Socket.hpp"
#include<unistd.h>
#include<stdio.h>
#include"Logger.hpp"


static const int _Num = 128;


class EpollServer
{
public:
    EpollServer(int _port):_listensockfd(std::make_unique<TcpSocket>()),_epfd(epoll_create(256))
    {
        _listensockfd->BulidSocket(_port);
        struct epoll_event _events;
        _events.events = EPOLLIN;
        _events.data.fd = _listensockfd->SockFd();

        int n = epoll_ctl(_epfd,EPOLL_CTL_ADD,_listensockfd->SockFd(),&_events);
        if(n < 0)
        {
            LOG(LogLevel::FATAL) << "add listensockfd failed";
            exit(1);
        }
    }

    void Accepter()
    {
        Inet_Addr _Client;
        int _sockfd = _listensockfd->Accept(&_Client);
        if(_sockfd < 0)
        {
            LOG(LogLevel::WARNING) << "accept failed";
        }

        else
        {
            struct epoll_event _events;
            _events.data.fd = _sockfd;
            _events.events = EPOLLIN;
            int n = epoll_ctl(_epfd,EPOLL_CTL_ADD,_sockfd,&_events);
            (void)n;
        }


    }


    void Recver(int i)
    {
        int _sockfd = _things[i].data.fd;

        char buffer[1024];

        ssize_t n = recv(_sockfd,buffer,sizeof(buffer)-1,0);
        if(n > 0)
        {
            buffer[n] = 0;
            std::cout << buffer;
            send(_sockfd,buffer,strlen(buffer),0);
        }

        else if(n == 0)
        {
            LOG(LogLevel::DEBUG) << "对端关闭";
            epoll_ctl(_epfd,EPOLL_CTL_DEL,_sockfd,nullptr);
            close(_sockfd);
        }

        else
        {
            LOG(LogLevel::ERROR) << "recv error";
            epoll_ctl(_epfd,EPOLL_CTL_DEL,_sockfd,nullptr);
            close(_sockfd);
        }

    }



    void Designator(int n)
    {
        for(int i = 0;i<n;i++)
        {
            if(_things[i].events & EPOLLIN)
            {
                if(_things[i].data.fd == _listensockfd->SockFd())
                {
                    Accepter();
                }

                else
                {
                    Recver(i);
                }
            }

            else if(_things[i].events & EPOLLOUT)
            {
                //...
            }


        }
    }



    void Start()
    {
        while(1)
        {
            int n = epoll_wait(_epfd,_things,_Num,-1);
            switch(n)
            {
                case 0:
                LOG(LogLevel::DEBUG) << "time out...";
                break;

                case -1:
                LOG(LogLevel::FATAL) << "epoll wait failed";
                break;

                default:
                Designator(n);
            }
        }
    }






    
    
    ~EpollServer()
    {}




private:
    std::unique_ptr<Socket> _listensockfd;
    int _epfd;
    struct epoll_event _things[128];
};








#endif
